package com.github.xiaoymin.knife4j.spring.util;

import org.springframework.beans.BeanUtils;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.PropertyBuilder;
import io.swagger.models.Model;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.DateTimeProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.ObjectProperty;
import io.swagger.models.properties.StringProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.IntegerProperty;
import java.util.HashMap;
import io.swagger.models.properties.AbstractProperty;
import java.util.Map;

public class SwaggerUtil
{
    private static boolean isBaseType(final String type) {
        return getSwaggerProperty(type) != null;
    }
    
    private static Map<String, AbstractProperty> getPropMap() {
        final Map<String, AbstractProperty> map = new HashMap<String, AbstractProperty>(8);
        map.put("integer", new IntegerProperty());
        map.put("int", new IntegerProperty());
        map.put("long", new LongProperty());
        map.put("string", new StringProperty());
        map.put("object", new ObjectProperty());
        map.put("array", new ArrayProperty());
        map.put("boolean", new BooleanProperty());
        map.put("date", new DateTimeProperty());
        return map;
    }
    
    private static AbstractProperty getSwaggerProperty(String type) {
        type = type.toLowerCase();
        return getPropMap().get(type);
    }
    
    private static boolean isMap(String type) {
        type = type.toLowerCase();
        return type.startsWith("map");
    }
    
    private static boolean isIterable(String type) {
        type = type.toLowerCase();
        return type.startsWith("list") || type.startsWith("set");
    }
    
    public static String getRef(final String type) {
        try {
            final String m = type.substring(type.lastIndexOf("«") + 1, type.indexOf("»"));
            final String[] split;
            final String[] cc = split = m.split(",");
            for (final String c : split) {
                if (!isBaseType(c)) {
                    return c;
                }
            }
            return type;
        }
        catch (Exception ex) {
            return "!!Unknown T!!";
        }
    }
    
    public static String getRealType(final String type) {
        try {
            return type.substring(type.indexOf("«") + 1, type.lastIndexOf("»"));
        }
        catch (Exception ex) {
            return type;
        }
    }
    
    private static boolean hasRef(final String type) {
        if (type.indexOf("»") > 0) {
            try {
                final String m = type.substring(type.lastIndexOf("«") + 1, type.indexOf("»"));
                final String[] split;
                final String[] cc = split = m.split(",");
                for (final String c : split) {
                    if (!isBaseType(c)) {
                        return true;
                    }
                }
                return false;
            }
            catch (Exception e) {
                return false;
            }
        }
        return !isBaseType(type);
    }
    
    public static Property getNewProp(final Property dataProp, final String type, final Map<String, Model> definitions) {
        Property newProp = null;
        final Model model = definitions.get(type);
        Map<String, Property> props = null;
        if (null != model) {
            props = (Map<String, Property>)model.getProperties();
        }
        if (null == props) {
            props = new HashMap<String, Property>(2);
        }
        final String realType = getRealType(type);
        if (isMap(type)) {
            final String[] realTypes = splitByComma(realType);
            final Map<PropertyBuilder.PropertyId, Object> argsK = new HashMap<PropertyBuilder.PropertyId, Object>(2);
            argsK.put(PropertyBuilder.PropertyId.DESCRIPTION, "Map的键");
            argsK.put(PropertyBuilder.PropertyId.TYPE, realTypes[0].toLowerCase());
            final AbstractProperty prop0 = getSwaggerProperty(realTypes[0]);
            Property propK = PropertyBuilder.build((null == prop0) ? "object" : prop0.getType(), (null == prop0) ? null : prop0.getFormat(), (Map)argsK);
            propK.setName("key");
            final Map<PropertyBuilder.PropertyId, Object> argsV = new HashMap<PropertyBuilder.PropertyId, Object>(2);
            argsV.put(PropertyBuilder.PropertyId.DESCRIPTION, "Map的值");
            argsV.put(PropertyBuilder.PropertyId.TYPE, realTypes[1].toLowerCase());
            final AbstractProperty prop2 = getSwaggerProperty(realTypes[1]);
            Property propV = PropertyBuilder.build((null == prop2) ? "object" : prop2.getType(), (null == prop2) ? null : prop2.getFormat(), (Map)argsV);
            propV.setName("value");
            if (!realType.equals(type)) {
                propK = getNewProp(propK, realTypes[0], definitions);
                propV = getNewProp(propV, realTypes[1], definitions);
            }
            props.put(propK.getName(), propK);
            props.put(propV.getName(), propV);
            newProp = (Property)new RefProperty();
            BeanUtils.copyProperties((Object)dataProp, (Object)newProp);
            ((RefProperty)newProp).set$ref(type);
        }
        else if (isIterable(type)) {
            final String ref = getRealType(type);
            newProp = (Property)new ArrayRefProperty();
            BeanUtils.copyProperties((Object)dataProp, (Object)newProp);
            ((ArrayRefProperty)newProp).set$ref(ref);
            ((ArrayRefProperty)newProp).setType("array");
            if (!realType.equals(type)) {
                getNewProp(dataProp, realType, definitions);
            }
        }
        else if (isBaseType(type)) {
            final Map<PropertyBuilder.PropertyId, Object> args = new HashMap<PropertyBuilder.PropertyId, Object>(2);
            args.put(PropertyBuilder.PropertyId.DESCRIPTION, dataProp.getDescription());
            args.put(PropertyBuilder.PropertyId.TYPE, type.toLowerCase());
            final AbstractProperty prop3 = getSwaggerProperty(type);
            newProp = PropertyBuilder.build(prop3.getType(), prop3.getFormat(), (Map)args);
            newProp.setName(dataProp.getName());
        }
        else if (hasRef(type)) {
            newProp = (Property)new RefProperty();
            BeanUtils.copyProperties((Object)dataProp, (Object)newProp);
            ((RefProperty)newProp).set$ref(type);
        }
        if (null != model) {
            model.setProperties((Map)props);
        }
        return newProp;
    }
    
    private static String[] splitByComma(final String str) {
        int index = 0;
        int has = 0;
        for (int i = 0; i < str.length(); ++i) {
            final char c = str.charAt(i);
            if ("«".equals(c + "")) {
                ++has;
            }
            if ("»".equals(c + "")) {
                --has;
            }
            if (",".equals(c + "") && has == 0) {
                index = i;
            }
        }
        final String[] arr = { str.substring(0, index), str.substring(index + 1) };
        return arr;
    }
    
    public static void main(final String[] args) {
        final String[] array;
        final String[] ss = array = new String[] { "A«List«C1»»", "A«C2»", "A«B«String,«String,List«C4»»»»" };
        for (final String s : array) {
            final String c = getRealType(s);
            System.out.println(c);
        }
        final String[] array2;
        final String[] s2 = array2 = new String[] { "A,B«List«C1»»", "Map«A,B»,C«List«D»»", "Map«Map«A,B»,C«List«D»»,Map«A,B»,C«List«D»»»,C«List«D»»" };
        for (final String s3 : array2) {
            final String[] arr = splitByComma(s3);
            System.out.println(arr[0]);
            System.out.println(arr[1]);
        }
    }
}
